use async_trait::async_trait;
use rustcloud_core::{Request, Response, ServiceError, ServiceResult, RequestContext};
use crate::advanced_proxy::{RequestInterceptor, ResponseInterceptor};
use std::time::{SystemTime, UNIX_EPOCH};
use std::collections::HashMap;
use serde_json;
use tracing::{info, warn, error};

/// 日志拦截器 - 记录请求和响应
pub struct LoggingInterceptor {
    name: String,
}

impl LoggingInterceptor {
    pub fn new() -> Self {
        Self {
            name: "LoggingInterceptor".to_string(),
        }
    }
}

#[async_trait]
impl RequestInterceptor for LoggingInterceptor {
    async fn before_request(&self, request: &mut Request, context: &RequestContext) -> ServiceResult<()> {
        info!(
            "[{}] Sending request: {} {} to service: {}",
            context.trace_id.as_deref().unwrap_or("unknown"),
            request.method,
            request.path,
            request.service_name
        );
        
        // 记录请求头信息
        if !request.headers.is_empty() {
            info!("Request headers: {:?}", request.headers);
        }
        
        Ok(())
    }
    
    fn name(&self) -> &str {
        &self.name
    }
    
    fn order(&self) -> i32 {
        100 // 较低优先级，最后执行
    }
}

#[async_trait]
impl ResponseInterceptor for LoggingInterceptor {
    async fn after_response(&self, request: &Request, response: &mut Response, context: &RequestContext) -> ServiceResult<()> {
        info!(
            "[{}] Received response: {} for {} {} ({}ms)",
            context.trace_id.as_deref().unwrap_or("unknown"),
            response.status,
            request.method,
            request.path,
            response.headers.get("x-response-time").unwrap_or(&"0".to_string())
        );
        
        if response.status >= 400 {
            warn!("Response contains error status: {}", response.status);
        }
        
        Ok(())
    }
    
    async fn on_error(&self, request: &Request, error: &ServiceError, context: &RequestContext) -> ServiceResult<()> {
        error!(
            "[{}] Request failed: {} {} - Error: {:?}",
            context.trace_id.as_deref().unwrap_or("unknown"),
            request.method,
            request.path,
            error
        );
        Ok(())
    }
    
    fn name(&self) -> &str {
        &self.name
    }
    
    fn order(&self) -> i32 {
        100 // 较低优先级，最后执行
    }
}

/// 追踪拦截器 - 添加分布式追踪信息
pub struct TracingInterceptor {
    name: String,
    service_name: String,
}

impl TracingInterceptor {
    pub fn new(service_name: String) -> Self {
        Self {
            name: "TracingInterceptor".to_string(),
            service_name,
        }
    }
    
    fn generate_trace_id() -> String {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_nanos();
        format!("{:x}", now)
    }
    
    fn generate_span_id() -> String {
        let now = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_micros();
        format!("{:x}", now % 0xFFFFFFFFFFFF) // 16位span id
    }
}

#[async_trait]
impl RequestInterceptor for TracingInterceptor {
    async fn before_request(&self, request: &mut Request, context: &RequestContext) -> ServiceResult<()> {
        // 添加或传播trace信息
        let trace_id = context.trace_id.clone().unwrap_or_else(|| Self::generate_trace_id());
        let span_id = Self::generate_span_id();
        
        request.add_header("x-trace-id", &trace_id);
        request.add_header("x-span-id", &span_id);
        request.add_header("x-parent-service", &self.service_name);
        
        // 添加时间戳
        let timestamp = SystemTime::now()
            .duration_since(UNIX_EPOCH)
            .unwrap_or_default()
            .as_millis();
        request.add_header("x-request-timestamp", &timestamp.to_string());
        
        Ok(())
    }
    
    fn name(&self) -> &str {
        &self.name
    }
    
    fn order(&self) -> i32 {
        10 // 高优先级，较早执行
    }
}

#[async_trait]
impl ResponseInterceptor for TracingInterceptor {
    async fn after_response(&self, request: &Request, response: &mut Response, _context: &RequestContext) -> ServiceResult<()> {
        // 计算请求耗时
        if let Some(timestamp_str) = request.headers.get("x-request-timestamp") {
            if let Ok(request_timestamp) = timestamp_str.parse::<u128>() {
                let now = SystemTime::now()
                    .duration_since(UNIX_EPOCH)
                    .unwrap_or_default()
                    .as_millis();
                let response_time = now - request_timestamp;
                response.add_header("x-response-time", &response_time.to_string());
            }
        }
        
        // 传播trace信息
        if let Some(trace_id) = request.headers.get("x-trace-id") {
            response.add_header("x-trace-id", trace_id);
        }
        if let Some(span_id) = request.headers.get("x-span-id") {
            response.add_header("x-span-id", span_id);
        }
        
        Ok(())
    }
    
    fn name(&self) -> &str {
        &self.name
    }
    
    fn order(&self) -> i32 {
        10 // 高优先级，较早执行
    }
}

/// 认证拦截器 - 添加认证信息
pub struct AuthenticationInterceptor {
    name: String,
    auth_token: Option<String>,
    auth_header: String,
}

impl AuthenticationInterceptor {
    pub fn new() -> Self {
        Self {
            name: "AuthenticationInterceptor".to_string(),
            auth_token: None,
            auth_header: "Authorization".to_string(),
        }
    }
    
    pub fn with_bearer_token(mut self, token: String) -> Self {
        self.auth_token = Some(format!("Bearer {}", token));
        self
    }
    
    pub fn with_api_key(mut self, api_key: String) -> Self {
        self.auth_token = Some(api_key);
        self.auth_header = "X-API-Key".to_string();
        self
    }
    
    pub fn with_custom_auth(mut self, header: String, value: String) -> Self {
        self.auth_header = header;
        self.auth_token = Some(value);
        self
    }
}

#[async_trait]
impl RequestInterceptor for AuthenticationInterceptor {
    async fn before_request(&self, request: &mut Request, _context: &RequestContext) -> ServiceResult<()> {
        if let Some(token) = &self.auth_token {
            request.add_header(&self.auth_header, token);
        }
        Ok(())
    }
    
    fn name(&self) -> &str {
        &self.name
    }
    
    fn order(&self) -> i32 {
        20 // 中等优先级
    }
}

impl Default for LoggingInterceptor {
    fn default() -> Self {
        Self::new()
    }
}

impl Default for AuthenticationInterceptor {
    fn default() -> Self {
        Self::new()
    }
}